package com.my.swas.common.utils.file;


import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;


/**
 * @作者: MaYong
 * @描述:
 * @版本 : V1.0
 */


public class DownloadUtils {
    /**
     * 文件下载编码
     * 该编码告诉浏览器文件名的编码方式，以防下载中文文件名时有乱码
     */
    private static String encoding = "utf-8";
    /**
     * 文件下载
     * @param response
     * @param filePath 文件在服务器上的路径，包含文件名
     */
    public static void download(HttpServletResponse response, String filePath){
        File file = new File(filePath.toString());
        download(response, file, null, encoding);
    }

    /**
     * 文件下载
     * @param response
     * @param filePath 文件在服务器上的路径，包括文件名称
     * @param fileName 文件下载到浏览器的名称，如果不想让浏览器下载的文件名称和服务器上的文件名称一样，请设置该参数
     */
    public static void download(HttpServletResponse response, String filePath, String fileName){
        File file = new File(filePath.toString());
        download(response, file, fileName, encoding);
    }

    /**
     * 文件下载
     * @param response
     * @param filePath 文件在服务器上的路径，包括文件名称
     * @param fileName 文件下载到浏览器的名称，如果不想让浏览器下载的文件名称和服务器上的文件名称一样，请设置该参数
     * @param encoding 文件名称编码
     */
    public static void download(HttpServletResponse response, String filePath, String fileName, String encoding){
        File file = new File(filePath.toString());
        download(response, file, fileName, encoding);
    }

    /**
     * 文件下载
     * @param response
     * @param file 文件
     */
    public static void download(HttpServletResponse response, File file) {
        download(response, file, null, encoding);
    }

    /**
     * 文件下载
     * @param response
     * @param file 文件
     * @param fileName 文件下载到浏览器的名称，如果不想让浏览器下载的文件名称和服务器上的文件名称一样，请设置该参数
     */
    public static void download(HttpServletResponse response, File file, String fileName) {
        download(response, file, fileName, encoding);
    }

    /**
     * 文件下载
     * @param response
     * @param file 文件
     * @param fileName 文件下载到浏览器的名称，如果不想让浏览器下载的文件名称和服务器上的文件名称一样，请设置该参数
     * @param encoding 文件名称编码
     */
    public static void download(HttpServletResponse response, File file, String fileName, String encoding) {
        /*if(file == null || !file.exists() || file.isDirectory()){
            return;
        }*/

        // 如果不指定文件下载到浏览器的名称，则使用文件的默认名称
        if (StringUtils.isBlank(fileName)) {
            fileName = file.getName();
        }

        try {
            InputStream is = new FileInputStream(file);
            download(response, is, fileName, encoding);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件下载
     * @param response
     * @param is 文件输入流
     * @param fileName 下载的文件名称
     * @throws IOException
     */
    public static void download(HttpServletResponse response, InputStream is, String fileName){
        download(response, is, fileName, encoding);
    }

    /**
     * 文件下载
     * @param response
     * @param is 文件输入流
     * @param fileName 下载的文件名称
     * @param encoding 编码格式
     */
    public static void download(HttpServletResponse response, InputStream is, String fileName, String encoding){
        if(is == null || StringUtils.isBlank(fileName)){
            return;
        }

        BufferedInputStream bis = null;
        OutputStream os = null;
        BufferedOutputStream bos = null;

        try{
            bis = new BufferedInputStream(is);
            os = response.getOutputStream();
            bos = new BufferedOutputStream(os);
            if(fileName.indexOf(".zip")>0){
                response.setContentType("application/zip");// 定义输出类型
            }else{
                response.setContentType("application/octet-stream;charset=" + encoding);
            }
            response.setCharacterEncoding(encoding);
            response.setHeader("Content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, encoding));
            response.setHeader("Accept-Ranges","bytes");
            byte[] buffer = new byte[1024];
            int len = bis.read(buffer);
            while(len != -1){
                bos.write(buffer, 0, len);
                len = bis.read(buffer);
            }

            bos.flush();
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            if(bis != null){
                try{
                    bis.close();
                }catch(IOException e){}
            }

            if(is != null){
                try{
                    is.close();
                }catch(IOException e){}
            }
        }
    }

    /**
     * @Name: downRemoteFile。
     * @Description: 下载远程文件。
     * @Parameters: remoteFileUrl，要下载的远程文件地址。
     * @Parameters: saveFileName，下载后保存的文件名。
     * @Parameters: saveDir，下载后保存的文件路径。
     * @Return: String，文件保存的地址。
     * @Author: PeiFeng
     * @Version: V1.00
     * @Create Date: 2017-8-12
     */
    public static String downRemoteFile(String remoteFileUrl, String saveFileName, String saveDir) {

        HttpURLConnection conn = null;
        OutputStream outputStream = null;
        InputStream iputStream = null;

        try {
            // 创建保存文件的目录
            File savePath = new File(saveDir);
            if (!savePath.exists()) {
                savePath.mkdir();
            }
            // 创建保存的文件
            File file = new File(savePath + "/" + saveFileName);
            if (file != null && !file.exists()) {
                file.createNewFile();
            }

            URL url = new URL(remoteFileUrl);
            // 将url以open方法返回的urlConnection连接强转为HttpURLConnection连接(标识一个url所引用的远程对象连接)
            // 此时cnnection只是为一个连接对象,待连接中
            conn = (HttpURLConnection) url.openConnection();
            // 设置是否要从 URL连接读取数据,默认为true
            conn.setDoInput(true);
            // 建立连接
            // (请求未开始,直到connection.getInputStream()方法调用时才发起,以上各个参数设置需在此方法之前进行)
            conn.connect();
            // 连接发起请求,处理服务器响应 (从连接获取到输入流)
            iputStream = conn.getInputStream();
            // 创建文件输出流，用于保存下载的远程文件
            outputStream = new FileOutputStream(file);
            //  用来存储响应数据
            byte[] buffer = new byte[4 * 1024];
            int byteRead = -1;
            //  循环读取流
            while ((byteRead = (iputStream.read(buffer))) != -1) {
                outputStream.write(buffer, 0, byteRead);
            }
            //  输出完成后刷新并关闭流
            outputStream.flush();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                //  重要且易忽略步骤 (关闭流,切记!)
                if (iputStream != null) {
                    iputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
                // 销毁连接
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 返回保存后的文件路径
        return saveDir + "/" + saveFileName;
    }

    public static String getEncoding() {
        return encoding;
    }

    public static void setEncoding(String encoding) {
        DownloadUtils.encoding = encoding;
    }
}
